{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<!--BOOK_INFORMATION-->\n",
    "<img align=\"left\" style=\"padding-right:10px;\" src=\"fig/cover-small.jpg\">\n",
    "*This notebook contains an excerpt from the [Whirlwind Tour of Python](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) by Jake VanderPlas; the content is available [on GitHub](https://github.com/jakevdp/WhirlwindTourOfPython).*\n",
    "\n",
    "*The text and code are released under the [CC0](https://github.com/jakevdp/WhirlwindTourOfPython/blob/master/LICENSE) license; see also the companion project, the [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook).*\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<!--NAVIGATION-->\n",
    "< [Built-In Data Structures](06-Built-in-Data-Structures.ipynb) | [Contents](Index.ipynb) | [Defining and Using Functions](08-Defining-Functions.ipynb) >"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Control Flow"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Control flow* is where the rubber really meets the road in programming.\n",
    "Without it, a program is simply a list of statements that are sequentially executed.\n",
    "With control flow, you can execute certain code blocks conditionally and/or repeatedly: these basic building blocks can be combined to create surprisingly sophisticated programs!\n",
    "\n",
    "Here we'll cover *conditional statements* (including \"``if``\", \"``elif``\", and \"``else``\"), *loop statements* (including \"``for``\" and \"``while``\" and the accompanying \"``break``\", \"``continue``\", and \"``pass``\")."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conditional Statements: ``if``-``elif``-``else``:\n",
    "Conditional statements, often referred to as *if-then* statements, allow the programmer to execute certain pieces of code depending on some Boolean condition.\n",
    "A basic example of a Python conditional statement is this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-15 is negative\n"
     ]
    }
   ],
   "source": [
    "x = -15\n",
    "\n",
    "if x == 0:\n",
    "    print(x, \"is zero\")\n",
    "elif x > 0:\n",
    "    print(x, \"is positive\")\n",
    "elif x < 0:\n",
    "    print(x, \"is negative\")\n",
    "else:\n",
    "    print(x, \"is unlike anything I've ever seen...\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note especially the use of colons (``:``) and whitespace to denote separate blocks of code.\n",
    "\n",
    "Python adopts the ``if`` and ``else`` often used in other languages; its more unique keyword is ``elif``, a contraction of \"else if\".\n",
    "In these conditional clauses, ``elif`` and ``else`` blocks are optional; additionally, you can optinally include as few or as many ``elif`` statements as you would like."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ``for`` loops\n",
    "Loops in Python are a way to repeatedly execute some code statement.\n",
    "So, for example, if we'd like to print each of the items in a list, we can use a ``for`` loop:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2 3 5 7 "
     ]
    }
   ],
   "source": [
    "for N in [2, 3, 5, 7]:\n",
    "    print(N, end=' ') # print all on same line"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice the simplicity of the ``for`` loop: we specify the variable we want to use, the sequence we want to loop over, and use the \"``in``\" operator to link them together in an intuitive and readable way.\n",
    "More precisely, the object to the right of the \"``in``\" can be any Python *iterator*.\n",
    "An iterator can be thought of as a generalized sequence, and we'll discuss them in [Iterators](10-Iterators.ipynb).\n",
    "\n",
    "For example, one of the most commonly-used iterators in Python is the ``range`` object, which generates a sequence of numbers:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 1 2 3 4 5 6 7 8 9 "
     ]
    }
   ],
   "source": [
    "for i in range(10):\n",
    "    print(i, end=' ')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the range starts at zero by default, and that by convention the top of the range is not included in the output.\n",
    "Range objects can also have more complicated values:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[5, 6, 7, 8, 9]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# range from 5 to 10\n",
    "list(range(5, 10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 2, 4, 6, 8]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# range from 0 to 10 by 2\n",
    "list(range(0, 10, 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You might notice that the meaning of ``range`` arguments is very similar to the slicing syntax that we covered in [Lists](06-Built-in-Data-Structures.ipynb#Lists).\n",
    "\n",
    "Note that the behavior of ``range()`` is one of the differences between Python 2 and Python 3: in Python 2, ``range()`` produces a list, while in Python 3, ``range()`` produces an iterable object."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ``while`` loops\n",
    "The other type of loop in Python is a ``while`` loop, which iterates until some condition is met:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 1 2 3 4 5 6 7 8 9 "
     ]
    }
   ],
   "source": [
    "i = 0\n",
    "while i < 10:\n",
    "    print(i, end=' ')\n",
    "    i += 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The argument of the ``while`` loop is evaluated as a boolean statement, and the loop is executed until the statement evaluates to False."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ``break`` and ``continue``: Fine-Tuning Your Loops\n",
    "There are two useful statements that can be used within loops to fine-tune how they are executed:\n",
    "\n",
    "- The ``break`` statement breaks-out of the loop entirely\n",
    "- The ``continue`` statement skips the remainder of the current loop, and goes to the next iteration\n",
    "\n",
    "These can be used in both ``for`` and ``while`` loops.\n",
    "\n",
    "Here is an example of using ``continue`` to print a string of odd numbers.\n",
    "In this case, the result could be accomplished just as well with an ``if-else`` statement, but sometimes the ``continue`` statement can be a more convenient way to express the idea you have in mind:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 3 5 7 9 11 13 15 17 19 "
     ]
    }
   ],
   "source": [
    "for n in range(20):\n",
    "    # if the remainder of n / 2 is 0, skip the rest of the loop\n",
    "    if n % 2 == 0:\n",
    "        continue\n",
    "    print(n, end=' ')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here is an example of a ``break`` statement used for a less trivial task.\n",
    "This loop will fill a list with all Fibonacci numbers up to a certain value:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]\n"
     ]
    }
   ],
   "source": [
    "a, b = 0, 1\n",
    "amax = 100\n",
    "L = []\n",
    "\n",
    "while True:\n",
    "    (a, b) = (b, a + b)\n",
    "    if a > amax:\n",
    "        break\n",
    "    L.append(a)\n",
    "\n",
    "print(L)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice that we use a ``while True`` loop, which will loop forever unless we have a break statement!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Loops with an ``else`` Block\n",
    "One rarely used pattern available in Python is the ``else`` statement as part of a ``for`` or ``while`` loop.\n",
    "We discussed the ``else`` block earlier: it executes if all the ``if`` and ``elif`` statements evaluate to ``False``.\n",
    "The loop-``else`` is perhaps one of the more confusingly-named statements in Python; I prefer to think of it as a ``nobreak`` statement: that is, the ``else`` block is executed only if the loop ends naturally, without encountering a ``break`` statement.\n",
    "\n",
    "As an example of where this might be useful, consider the following (non-optimized) implementation of the *Sieve of Eratosthenes*, a well-known algorithm for finding prime numbers:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]\n"
     ]
    }
   ],
   "source": [
    "L = []\n",
    "nmax = 30\n",
    "\n",
    "for n in range(2, nmax):\n",
    "    for factor in L:\n",
    "        if n % factor == 0:\n",
    "            break\n",
    "    else: # no break\n",
    "        L.append(n)\n",
    "print(L)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The ``else`` statement only executes if none of the factors divide the given number.\n",
    "The ``else`` statement works similarly with the ``while`` loop."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<!--NAVIGATION-->\n",
    "< [Built-In Data Structures](06-Built-in-Data-Structures.ipynb) | [Contents](Index.ipynb) | [Defining and Using Functions](08-Defining-Functions.ipynb) >"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
